// RAF  ---   定时器
class Interval {
  #timerId = null
  #loop = null
  #count = 0
  #timer = Date.now()
  #return = false
  // 构造器
  constructor(cb, time = 0) {
    if(typeof (time * 1) !== 'number') {
      cb(new Error('抱歉! 您的时间参数必须为 数字类型 或者 字符串数字类型'))
      return
    }
    this.#loop = () => {
      if(Date.now() > this.#timer + time * (this.#count + 1)){
        cb(this.#count)
        this.#count++
      }
      if(this.#return) return // 如果标识为true 就是停止定时器
      this.#timerId = requestAnimationFrame(this.#loop)
    }
    this.#timerId = requestAnimationFrame(this.#loop)
  }
  // 清除定时器
  clear() {
    this.#return = true // 改变标识为 true
    cancelAnimationFrame(this.#timerId) // 清除 requestAnimationFrame
  }
}

// 高性能、炫酷的渲染图片的插件 ( 超级优化版 )
export default class HandsomeImageLoading {
  #wrap = null // 容器
  #wrap_width = 0 // 容器宽度
  #wrap_height = 0 // 容器高度
  #img_width = 150
  #img_height = 150
  #num = 0
  #ge = 0
  #time = 3 // 延迟加载倍率 3 --> 0~2000
  #imglist = [] // 图片地址列表
  #font_special_img = [] // 前面特效元素数组
  #end_special_img = [] //  没有特效元素数组
  #layout_wrap = document.createElement('div')
  #layout_wrap_top = document.createElement('div')
  #layout_wrap_bottom = document.createElement('div')
  #imgOverArr = []
  #endimgOverArr = []
  #maxTime = []
  #fragment = document.createDocumentFragment()
  #fragment_bottom = document.createDocumentFragment()
  constructor(wrap = null, imglist = []) {
    let t = this
    t.#wrap = wrap
    t.#wrap_width = wrap.getBoundingClientRect().width
    t.#wrap_height = wrap.getBoundingClientRect().height
    t.#imglist = imglist
  }

  // 展示特效
  start = () => {
    let t = this
    t.#create_layout(t)
    // 渲染特效列表
    .then(res => {
      t.#imgOverArr.forEach(item => {
        t.#random_show(item, t)
      })
    })
  }

  // 设置每个图片的随机展示
  #random_show = (item, t) => {
    let num = 1000
    let timeout = null
    let timer = null
    let randomNum = (Math.random() * t.#time).toFixed(3) * 1
    t.#maxTime.push(randomNum)
    timeout = setTimeout(() => {
      timer = new Interval((val) => {
        if(num === 0) {
          timer.clear()
          t.#maxTime.shift()
          // 所有动画都完毕的钩子
          if(t.#maxTime.length == 0) {
            t.#wrap.style.overflow = 'auto';
          }
        }
        item.style['z-index'] = Math.floor(randomNum * 10) // z-index越久越大
        item.style.transform = `translateZ(${ num }px)`;
        num -= 10
      }, 10)
      clearTimeout(timeout)
    }, randomNum * 1000)
  }

  // 创建布局容器
  #create_layout = t => {
    return new Promise(resolve => {
      t.#layout_wrap.id = 'layout-wrap'
      t.#layout_wrap.style.cssText = 'width: 100%; height: 100%; overflow: auto;'
      t.#layout_wrap_top.id = 'layout-wrap-top'
      t.#layout_wrap_top.style.cssText = `width: 100%; height: 100%;transform-style: preserve-3d;perspective: 800px;`
      t.#layout_wrap_bottom.id = 'layout-wrap-bottom'
      t.#layout_wrap.appendChild(t.#layout_wrap_top)
      t.#layout_wrap.appendChild(t.#layout_wrap_bottom)
      t.#wrap.appendChild(t.#layout_wrap)
      // 监测这个容器的变化
      t.#change(t).then(res => {
        // 创建图片
        t.#create_img(t, resolve)
        // 创建非特效图片
        t.#create_img_no_animate(t, resolve)
      })
    })
  }

  #change = t => {
    return new Promise(resolve => {
      let ob = new ResizeObserver(entries => {
        t.#computed(t, entries[0].contentRect.width, entries[0].contentRect.height, resolve)
      })
      ob.observe(t.#layout_wrap)
    })
  }

  #create_img = async(t, rsl) => {
    t.#font_special_img = JSON.parse(JSON.stringify(t.#imglist)).slice(0, t.#num)
    t.#font_special_img.forEach((item, index) => {
      let img = new Image()
      img.src = item
      img.draggable = ''
      img.style.cssText = `
      width: ${ t.#img_width }px;
      height: ${ t.#img_height }px;
      border: 2px solid #fff;
      cursor: pointer;
      position: relative;
      box-sizing: border-box;
      transform: translateZ(1000px);
      vertical-align: middle;
      `
      t.#imgOverArr.push(img)
      t.#fragment.appendChild(img)
    })
    // 所有图片加载完毕，再上树
    await Promise.all(t.#imgOverArr.map((img) => new Promise(resolve => img.addEventListener('load',()=> resolve(img))))).then(res => {
     t.#layout_wrap_top.appendChild(t.#fragment)
     rsl(true)
    })
  }

  #create_img_no_animate = async(t, rsl) => {
    t.#end_special_img = JSON.parse(JSON.stringify(t.#imglist)).slice(t.#num)
    t.#end_special_img.forEach(item => {
      let img = new Image()
      img.src = ''
      img.setAttribute('falsesrc', item)
      img.draggable = ''
      img.style.cssText = `
      width: ${ t.#img_width }px;
      height: ${ t.#img_height }px;
      border: 2px solid #fff;
      cursor: pointer;
      position: relative;
      box-sizing: border-box;
      vertical-align: middle;
      `
      t.#endimgOverArr.push(img)
      t.#fragment_bottom.appendChild(img)
    })
    t.#layout_wrap_bottom.appendChild(t.#fragment_bottom)
    // 所有图片加载完毕，再上树
    await Promise.all(t.#endimgOverArr.map((img) => new Promise(resolve => img.addEventListener('load',()=> resolve(img))))).then(res => {
      // t.#layout_wrap_bottom.appendChild(t.#fragment_bottom)
      console.log(res);
      rsl(true)
     })
  }

  // 初始化margin
  #init_margin = (t) => {
    t.#ge = Math.floor(t.#wrap_width / t.#img_width)
    return (t.#wrap_width - t.#img_width * t.#ge) / (t.#ge - 1)
  }

  // 计算
  #computed = (t, width, height, resolve) => {
    // t.#layout_wrap_bottom.style.
    console.log(t.#layout_wrap_top.getBoundingClientRect());
    t.#num = Math.floor(width / t.#img_width) * Math.ceil(height / t.#img_height)
    t.#ge =Math.floor(width / t.#img_width)
    resolve(Math.floor(width / t.#img_width) * Math.ceil(height / t.#img_height))

    t.#imgOverArr.forEach((item, index) => {
      if((index + 1) % t.#ge === 0) {
        item.style.marginRight = 0
      }else {
        item.style.marginRight = `${ (width - t.#img_width * t.#ge) / (t.#ge - 1) }px`
      }
      item.style.marginBottom = `${ (width - t.#img_width * t.#ge) / (t.#ge - 1) }px`
    })

    // 底部margin
    t.#endimgOverArr.forEach((item, index) => {
      if((index + 1) % t.#ge === 0) {
        item.style.marginRight = 0
      }else {
        item.style.marginRight = `${ (width - t.#img_width * t.#ge) / (t.#ge - 1) }px`
      }
      item.style.marginBottom = `${ (width - t.#img_width * t.#ge) / (t.#ge - 1) }px`
    })
  }
}